 1.利用map join特性
   
   map join特别适合大小表join的情况。Hive会将build table和probe table在map端
直接完成join过程，消灭了reduce，效率很高。
  select a.event_type, b.upload_time
from calendar_event_code a
inner join (
select event_type, upload_time from calendar_record_log
where pt_date = 20190225
) b on a.event_type = b.event_type;
   map join的配置项是 hive.auto.convert.join ，默认值true。
   当build table大小小于 hive.mapjoin.smalltable.filesize 会启用map join，默
认值25000000（约25MB）。还有 hive.mapjoin.cache.numrows ，表示缓存build table
的多少行数据到内存，默认值25000。
 
 2.分桶表map join
   
   map join对分桶表还有特别的优化。由于分桶表是基于一列进行hash存储的，因此
非常适合抽样（按桶或按块抽样）。它对应的配置项是
   hive.optimize.bucketmapjoin 。
 
 3.倾斜均衡配置项
   
   这个配置与 group by 的倾斜均衡配置项异曲同工，通过 hive.optimize.skewjoin
来配置，默认false。
   如果开启了，在join过程中Hive会将计数超过阈值 hive.skewjoin.key (默认
100000)的倾斜key对应的行临时写进文件中，然后再启动另一个job做map join生成
结果。通过 hive.skewjoin.mapjoin.map.tasks 参数还可以控制第二个job的mapper
数量，默认10000。
 
 4.处理空值或无意义值
   
   日志类数据中往往会有一些项没有记录到，其值为null，或者空字符串、-1等。如果
缺失的项很多，在做join时这些空值就会非常集中，拖累进度【备注：这个字段是连
接字段】。
   若不需要空值数据，就提前写 where 语句过滤掉。需要保留的话，将空值key用随机
方式打散，例如将用户ID为null的记录随机改为负值：
   select a.uid, a.event_type, b.nickname, b.age
from (
 select
 (case when uid is null then cast(rand()*-10240 as int) else
uid end) as uid,
event_type from calendar_record_log
where pt_date >= 20190201
) a left outer join (
select uid,nickname,age from user_info where status = 4
) b on a.uid = b.uid;
 
 5.单独处理倾斜key
   
   如果倾斜的 key 有实际的意义，一般来讲倾斜的key都很少，此时可以将它们单独抽
取出来，对应的行单独存入临时表中，然后打上一个较小的随机数前缀(比如0~9)，最后
再进行聚合。
   不要一个Select语句中，写太多的Join。一定要了解业务，了解数据。(A0-A9)
   分成多条语句，分步执行；(A0-A4; A5-A9)；先执行大表与小表的关联；
   